package com.yjw.demo.mybatis.common.util;

import java.io.IOException;
import java.util.List;

import com.yjw.demo.mybatis.common.page.Page;
import org.springframework.beans.BeanUtils;

import com.google.common.collect.Lists;
import com.yjw.demo.mybatis.common.exception.BaseException;
import com.yjw.demo.mybatis.common.pojo.PageResult;

/**
 * Bean 对象转换
 * 
 * <pre>
 * 1.Javabean 转换
 * 2.集合中所有对象转换
 * 3.分页对象转换
 * </pre>
 * 
 * @author yinjianwei
 * @date 2017/12/13
 */
public class BeanMapperUtils {

    /**
     * 私有化构造函数
     */
    private BeanMapperUtils() {

    }

    /**
     * Java对象转换
     * 
     * @param source 原属性
     * @param targetClass 目标类类型
     * @return
     * @throws ReflectiveOperationException
     */
    public static <T> T map(Object source, Class<T> targetClass) throws ReflectiveOperationException {
        T target = targetClass.newInstance();
        BeanUtils.copyProperties(source, target);
        return target;
    }

    /**
     * 通过JSON序列化反序列化实现Java对象属性深度拷贝
     * 
     * @param source
     * @param targetClass
     * @return
     * @throws IOException
     */
    public static <T> T mapByJson(Object source, Class<T> targetClass) throws IOException {
        String sourceJson = JsonUtils.toJSONString(source);
        return JsonUtils.parseObject(sourceJson, targetClass);
    }

    /**
     * 集合中所有对象转换
     * 
     * @param sources 原属性集合
     * @param targetClass List中目标类类型
     * @return
     * @throws ReflectiveOperationException
     */
    public static <S, T> List<T> mapList(List<S> sources, Class<T> targetClass) throws ReflectiveOperationException {
        List<T> targets = Lists.newArrayListWithCapacity(sources.size());
        for (Object source : sources) {
            T target = map(source, targetClass);
            targets.add(target);
        }
        return targets;
    }

    /**
     * 通过JSON序列化反序列化实现集合中所有对象转换
     * 
     * @param sources 原属性集合
     * @return
     * @throws IOException
     */
    public static <S, T> List<T> mapListByJson(List<S> sources) throws IOException {
        String sourceJson = JsonUtils.toJSONString(sources);
        return JsonUtils.parseList(sourceJson);
    }

    /**
     * 通过JSON序列化反序列化实现集合中所有对象转换
     * 
     * @param sources 原属性集合
     * @param clzss 需要处理字段的真实类型
     * @param includeFields 包含字段
     * @param filterFields 过滤字段
     * @return
     * @throws IOException
     */
    public static <S, T> List<T> mapListByJson(List<S> sources, Class<S> clzss, String includeFields,
        String filterFields) throws IOException {
        String sourceJson = JsonUtils.toJSONString(sources, clzss, includeFields, filterFields);
        return JsonUtils.parseList(sourceJson);
    }

    /**
     * 分页对象转换
     * 
     * <pre>
     * 1. 分页对象改为自定义分页对象
     * 2. 分页中数据对象转换
     * </pre>
     * 
     * @param list 原属性page集合
     * @param targetClass Page中目标类类型
     * @return
     * @throws ReflectiveOperationException
     */
    public static <S, T> PageResult<T> mapPage(List<S> list, Class<T> targetClass) throws ReflectiveOperationException {
        // 判断类型
        if (!(list instanceof Page)) {
            throw new BaseException("请在使用分页查询前调用PageHelper.startPage(pageNum, pageSize)");
        }
        Page<S> sourcesPage = (Page<S>)list;
        PageResult<T> pageResult = new PageResult<>(sourcesPage.getPageNum(), sourcesPage.getPageSize(),
            sourcesPage.getTotal(), sourcesPage.getPages());
        List<S> sources = sourcesPage.getResult();
        List<T> targets = Lists.newArrayListWithCapacity(sources.size());
        for (Object source : sources) {
            T target = map(source, targetClass);
            targets.add(target);
        }
        pageResult.setList(targets);
        return pageResult;
    }

    /**
     * 通过JSON序列化反序列化分页对象转换
     * 
     * <pre>
     * 1. 分页对象改为自定义分页对象
     * 2. 分页中数据对象转换
     * </pre>
     * 
     * @param list 原属性page集合
     * @return
     * @throws IOException
     */
    public static <S, T> PageResult<T> mapPageByJson(List<S> list) throws IOException {
        // 判断类型
        if (!(list instanceof Page)) {
            throw new BaseException("请在使用分页查询前调用PageHelper.startPage(pageNum, pageSize)");
        }
        Page<S> sourcesPage = (Page<S>)list;
        PageResult<T> pageResult = new PageResult<>(sourcesPage.getPageNum(), sourcesPage.getPageSize(),
            sourcesPage.getTotal(), sourcesPage.getPages());
        List<S> sources = sourcesPage.getResult();
        List<T> targets = mapListByJson(sources);
        pageResult.setList(targets);
        return pageResult;
    }

    /**
     * 通过JSON序列化反序列化分页对象转换
     * 
     * <pre>
     * 1. 分页对象改为自定义分页对象
     * 2. 分页中数据对象转换
     * </pre>
     * 
     * @param list 原属性page集合
     * @param clzss 需要处理字段的真实类型
     * @param includeFields 包含字段
     * @param includeFields 过滤字段
     * @return
     * @throws IOException
     */
    public static <S, T> PageResult<T> mapPageByJson(List<S> list, Class<S> clzss, String includeFields,
        String filterFields) throws IOException {
        // 判断类型
        if (!(list instanceof Page)) {
            throw new BaseException("请在使用分页查询前调用PageHelper.startPage(pageNum, pageSize)");
        }
        Page<S> sourcesPage = (Page<S>)list;
        PageResult<T> pageResult = new PageResult<>(sourcesPage.getPageNum(), sourcesPage.getPageSize(),
            sourcesPage.getTotal(), sourcesPage.getPages());
        List<S> sources = sourcesPage.getResult();
        List<T> targets = mapListByJson(sources, clzss, includeFields, filterFields);
        pageResult.setList(targets);
        return pageResult;
    }

}
